package com.destin.basic.util;

import com.destin.basic.security.SecurityProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ：destin
 * @date ：2022-03-23
 * @version: V1.0
 * @description: JWT token工具类
**/
@Slf4j
public class JwtTokenUtils {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_ID = "jti";
    private static final String CLAIM_KEY_CREATED = "created";

    // 创建token
    public static String createToken(String username, Long id, boolean isRememberMe) {
        long expiration = isRememberMe ? SecurityProperties.expirationRemember : SecurityProperties.expiration;
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USERNAME, username);
        claims.put(CLAIM_KEY_ID, id);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate(expiration))
                .signWith(SignatureAlgorithm.HS512, SecurityProperties.base64Secret)
                .compact();
    }

    /**
     * 生成token的过期时间
     */
    private static Date generateExpirationDate(long expiration) {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    /**
     * 从token中获取用户名
     * @param token
     * @return 用户名
     */
    public static String getUsername(String token){
        return getTokenBody(token).getSubject();
    }

    /**
     * 从token中获取 用户id
     * @param token
     * @return 用户id
     */
    public static String getId(String token){
        return getTokenBody(token).getId();
    }

    // 是否已过期
    public static boolean isExpiration(String token) {
        try {
            // 如果不超期，我们将续期
            Date date = new Date();
            Date expiration = getTokenBody(token).getExpiration();
            Boolean expirationBool = expiration.before(date);
            if(!expirationBool){
                getTokenBody(token).setExpiration(new Date(date.getTime() + 60*60*1000L));
            }
            return expirationBool;
        } catch (ExpiredJwtException e) {
            return true;
        }
    }

    private static Claims getTokenBody(String token){
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(SecurityProperties.base64Secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.info("JWT格式验证失败:{}", token);
        }
        return claims;
    }
}
